/**
 * 十六进制串转为buffer的类型
 * @param hex 十六进制串 类似于 eb902244..09d7
 * @returns {ArrayBuffer}
 */
export function hexToBuffer(hex) {
    const length = hex.length / 2;
    const buffer = new ArrayBuffer(length);
    const view = new Uint8Array(buffer);
    for (let i = 0; i < length; i++) {
        view[i] = parseInt(hex.substr(i * 2, 2), 16);
    }
    return buffer;
}

/**
 * 按 类型和位数解析十六进制字符串数据
 * @param hexString 十六进制串 类似 -> 'EB904422...09D7'
 * @param formatList 需要格式化成的类型和位数 类似 -> ['uint32', 'int16', 'float32', ...]
 * @returns {Array<Number>}
 */
function parseHexData(hexString, formatList) {
    // 预处理格式列表
    const preFormats = formatList.map(fmt => {
        const type = fmt.replace(/\d+/, '');
        const bits = parseInt(fmt.match(/\d+/)?.[0] || (type === 'float' ? 32 : 0));
        return {type, bits};
    });

    // 缓冲区初始化
    let buffer;
    if (hexString instanceof ArrayBuffer) {
        buffer = new Uint8Array(hexString);
    } else {
        const hexReg = /.{2}/g;
        const bytes = (hexString.match(hexReg) || []).map(b => parseInt(b, 16));
        buffer = new Uint8Array(bytes);
    }

    // 预计算掩码表
    const BIT_MASKS = new Array(33).fill(0).map((_, n) => (1 << n) - 1);

    // 浮点数处理池
    const floatBuffers = {
        32: new ArrayBuffer(4),
        64: new ArrayBuffer(8)
    };
    const floatViews = {
        32: new DataView(floatBuffers[32]),
        64: new DataView(floatBuffers[64])
    };

    const byteArray = new Uint8Array(buffer.buffer);
    let byteCursor = 0;
    let bitCursor = 0;
    const result = [];

    for (const {type, bits} of preFormats) {
        let value = 0;
        let remaining = bits;

        // 优化核心读取逻辑
        while (remaining > 0) {
            const bitsAvailable = 8 - bitCursor;
            const bitsToRead = Math.min(bitsAvailable, remaining);
            const mask = BIT_MASKS[bitsToRead];

            const byteValue = byteArray[byteCursor];
            const shifted = byteValue >> (8 - bitCursor - bitsToRead);
            value = value * (1 << bitsToRead) + (shifted & mask);

            remaining -= bitsToRead;
            bitCursor += bitsToRead;

            if (bitCursor >= 8) {
                byteCursor++;
                bitCursor = 0;
            }
        }

        // 类型处理优化
        switch (type) {
            case 'uint':
                result.push(value);
                break;
            case 'int':
                result.push(value >= (1 << (bits - 1)) ? value - (1 << bits) : value);
                break;
            case 'float':
                const view = floatViews[bits];
                view.setUint32(0, value);
                result.push(bits === 32 ? view.getFloat32(0) : view.getFloat64(0));
                break;
        }
    }

    return result;
}

/**
 * v2按类型和所占位数解析十六进制字符串数据
 * @param buffer arrayBuffer
 * @param types 需要格式化成的类型和位数 类似 -> ['uint32', 'int16', 'float32', ...]
 * @param littleEndian 是否使用小端序, 默认为大端序
 * @param adaptive 是否自适应解析, 默认自适应
 * @returns {Array<Number>}
 */
export function parseArrayBuffer(buffer, types, littleEndian = false, adaptive = false) {
    if (!buffer || buffer.byteLength === 0) {
        console.warn('Empty buffer passed to parser');
        return [];
    }
    if (!(buffer instanceof ArrayBuffer)) {
        const hexReg = /.{2}/g;
        const bytes = (buffer.match(hexReg) || []).map(b => parseInt(b, 16));
        buffer = new Uint8Array(bytes).buffer;
    }

    const view = new DataView(buffer);
    let byteOffset = 0;
    let bitOffset = 0;
    let currentByte = 0;
    const result = [];

    // 传统模式下读越界直接抛异常，自适应模式下返回 null
    function canReadBytes(offset, bytesCount) {
        return offset + bytesCount <= view.byteLength;
    }

    function safeRead(fn, offset, size) {
        if (!adaptive) {
            // 传统模式：不判断，直接调用，越界自然抛错
            return fn(offset);
        } else {
            // 自适应模式：检查边界，越界返回null
            if (!canReadBytes(offset, size)) return null;
            return fn(offset);
        }
    }

    function safeGetUint8(offset) {
        return safeRead(o => view.getUint8(o), offset, 1);
    }

    function safeGetInt8(offset) {
        return safeRead(o => view.getInt8(o), offset, 1);
    }

    function safeGetUint16(offset) {
        return safeRead(o => view.getUint16(o, littleEndian), offset, 2);
    }

    function safeGetInt16(offset) {
        return safeRead(o => view.getInt16(o, littleEndian), offset, 2);
    }

    function safeGetUint32(offset) {
        return safeRead(o => view.getUint32(o, littleEndian), offset, 4);
    }

    function safeGetInt32(offset) {
        return safeRead(o => view.getInt32(o, littleEndian), offset, 4);
    }

    function safeGetFloat32(offset) {
        return safeRead(o => view.getFloat32(o, littleEndian), offset, 4);
    }

    function safeGetFloat64(offset) {
        return safeRead(o => view.getFloat64(o, littleEndian), offset, 8);
    }

    for (const typeStr of types) {
        let dataType, bits;
        const intMatch = typeStr.match(/^(u?int)(\d+)$/);
        const floatMatch = typeStr.match(/^(float)(32|64)$/);

        if (intMatch) {
            dataType = intMatch[1];
            bits = parseInt(intMatch[2], 10);
        } else if (floatMatch) {
            dataType = floatMatch[1];
            bits = parseInt(floatMatch[2], 10);
        } else {
            throw new Error(`Invalid type: ${typeStr}`);
        }

        if (dataType === 'float') {
            if (bitOffset !== 0) {
                throw new Error(`Float type ${typeStr} must be byte-aligned`);
            }
            let value = null;
            if (bits === 32) {
                value = safeGetFloat32(byteOffset);
                if (value !== null) byteOffset += 4;
            } else if (bits === 64) {
                value = safeGetFloat64(byteOffset);
                if (value !== null) byteOffset += 8;
            } else {
                throw new Error(`Unsupported float bits: ${bits}`);
            }
            result.push(value);
            continue;
        }

        const isUnsigned = dataType === 'uint';
        const standardBits = [8, 16, 32];

        if (standardBits.includes(bits) && bitOffset === 0) {
            let value = null;
            switch (bits) {
                case 8:
                    value = isUnsigned ? safeGetUint8(byteOffset) : safeGetInt8(byteOffset);
                    if (value !== null) byteOffset += 1;
                    break;
                case 16:
                    value = isUnsigned ? safeGetUint16(byteOffset) : safeGetInt16(byteOffset);
                    if (value !== null) byteOffset += 2;
                    break;
                case 32:
                    value = isUnsigned ? safeGetUint32(byteOffset) : safeGetInt32(byteOffset);
                    if (value !== null) byteOffset += 4;
                    break;
            }
            result.push(value);
        } else {
            // 处理非标准位宽
            let value = 0;
            let bitsRead = 0;
            let canReadFully = true;

            while (bitsRead < bits) {
                if (bitOffset === 0) {
                    const byteVal = safeGetUint8(byteOffset);
                    if (byteVal === null) {
                        canReadFully = false;
                        break;
                    }
                    currentByte = byteVal;
                }

                const availableBits = 8 - bitOffset;
                const neededBits = bits - bitsRead;
                const readingBits = Math.min(availableBits, neededBits);

                const shift = availableBits - readingBits;
                const mask = (1 << readingBits) - 1;
                const part = (currentByte >>> shift) & mask;

                value = (value << readingBits) | part;

                bitOffset += readingBits;
                bitsRead += readingBits;

                if (bitOffset === 8) {
                    byteOffset++;
                    bitOffset = 0;
                }
            }

            if (!canReadFully) {
                result.push(null);
            } else {
                if (!isUnsigned && (value & (1 << (bits - 1)))) {
                    value -= (1 << bits);
                }
                result.push(value);
            }
        }
    }

    return result;
}


/**
 * 解析并计算遥测中处理函数
 * @param expr 公式字符串
 * @param value 提供遥测值
 * @returns {any} 计算结果
 */
const exprCache = new Map();

function evaluateExpression(expr, value) {
    // 预处理表达式
    expr = expr.replace(/\s/g, '')
        .replace(/^.*?=/, '')
        .replace(/\bX\b/gi, '(x)')  // 统一变量名为小写x
        .replace(/\bpi\b/gi, 'Math.PI')
        .replace(/\bpow\(/gi, 'Math.pow(');

    // 缓存编译后的函数
    if (!exprCache.has(expr)) {
        exprCache.set(expr, new Function('x', `return ${expr};`));
    }

    try {
        return exprCache.get(expr)(value);
    } catch (error) {
        console.error(`Error in expression: ${expr}`, error);
    }
}

/**
 * 将十进制整数转成16进制(支持处理负数)
 * @param decimal
 * @param pad 按位填充0
 * @returns {string}
 */
function decimalToHex(decimal, pad = 8) {
    return `0x${(decimal >>> 0).toString(16).padStart(pad, '0').toUpperCase()}`;
}


/**
 * 解析光学头遥测
 * @param opticalConfig 光学头配置对象, 请直接给出array类型的参数集合
 * @param hexString 原始十六进制串 EB90...09D7
 * @param adaptive 自适应解析
 * @param formatList 类似这样的数组按此位数截取 -> ["uint8", "uint32", "float32", ...]
 * @returns {Array<Object>}
 */
export function telemetryParser(opticalConfig, hexString, adaptive, formatList = formatList) {
    // 解析遥测数据成对象
    let dataArray = parseArrayBuffer(hexString, formatList, false, adaptive);
    return opticalConfig.map((item, index) => {
        // 处理枚举值
        if (item.enum && dataArray[index] !== null) {
            /* enum的key转全大写,统一对应*/
            function keysToUpperCase(obj) {
                return Object.fromEntries(
                    Object.entries(obj).map(([key, value]) => [key.toUpperCase(), value])
                );
            }

            /*将key归一化为dec*/
            function normalization(obj) {
                return Object.fromEntries(
                    Object.entries(obj).map(([key, value]) => [parseInt(key), value])
                );
            }

            return {
                label: item.name,
                // 直接dec取值 or 格式化字符串 or hex取值 or 归一化key为hex后对比hex取值(5层取值中间件)
                value: item.enum[dataArray[index]] ||
                    item.enum[dataArray[index].toString(16)] ||
                    item.enum[decimalToHex(dataArray[index], item.bit_length / 4)] ||
                    keysToUpperCase(item.enum)[decimalToHex(dataArray[index], item.bit_length / 4).toUpperCase()] ||
                    normalization(item.enum)[dataArray[index]]
                ,
                raw: dataArray[index],
                sourceCode: decimalToHex(dataArray[index], item.bit_length / 4),
                bitLength: item.bit_length
            }
            // 处理解析函数
        } else if (item.handler_func) {
            let actualValue = evaluateExpression(item.handler_func, dataArray[index])
            return {
                label: item.name,
                value: actualValue,
                raw: dataArray[index],
                sourceCode: decimalToHex(dataArray[index], item.bit_length / 4),
                bitLength: item.bit_length
            }
        }
        // 处理图像
        if (item.extra && item.extra === "image") {
            // item.extra == 'image'
            return {
                label: item.name,
                value: decimalToHex(dataArray[index], item.bit_length / 4).toUpperCase(),
                raw: decimalToHex(dataArray[index], item.bit_length / 4),
                sourceCode: decimalToHex(dataArray[index], item.bit_length / 4),
                bitLength: item.bit_length
            }
        }
        return {
            // 普通值
            label: item.name,
            value: dataArray[index],
            raw: dataArray[index],
            sourceCode: decimalToHex(dataArray[index], item.bit_length / 4),
            bitLength: item.bit_length
        }
    })
}

/**
 * 计算校验和建议请使用toByteArray先转换成字节数组
 * @param bytes uint8Array
 * @returns {string}
 */
export function calculateChecksum(bytes) {
    // 计算字节和
    let sum = bytes.reduce((acc, byte) => acc + byte, 0);

    // 取低8位 (sum % 256)
    let checksum = sum & 0xff;

    // 返回校验和，转换成2位的16进制字符串
    return checksum.toString(16).padStart(2, '0').toUpperCase();
}


/**
 * 提供一条指令的所有元素, 返回一个Uint8数组元素均被逐字节拆分(1byte)
 * @param params  keys: [bit_length, default]为必须
 * @returns {Uint8Array}
 */
export function toByteArray(params) {
    let result = [];

    params.forEach(item => {
        let value = item.default;
        let bitLength = parseInt(item.bit_length, 10);

        // 如果是十六进制字符串，先转换为整数
        if (typeof value === 'string' && value.startsWith('0x')) {
            value = parseInt(value, 16);
        }

        // 处理负数的补码
        if (value < 0) {
            let maxValue = Math.pow(2, bitLength);
            value = maxValue + value;  // 负数补码转换
        }

        // 计算字节数
        let byteCount = Math.ceil(bitLength / 8);

        // 填充数据到字节数组
        for (let i = 0; i < byteCount; i++) {
            let byte = (value >> (8 * (byteCount - i - 1))) & 0xFF;
            result.push(byte);
        }

        // 如果字节数不够位数，补充0字节
        while (result.length < Math.ceil(bitLength / 8)) {
            result.push(0);
        }
    });

    return new Uint8Array(result);
}

export const sourceCodeHex = (params) => {
    if (!params) {
        return "";
    }
    console.log(params);

    // 拼接所有的默认值，并去掉0x前缀，同时处理负数的情况
    const hexString = params
        .map((item) => {
            let {default: defaultValue} = item;
            if (typeof defaultValue === "number") {
                // 如果是负数，将其转换为补码形式
                if (defaultValue < 0) {
                    // 假设需要处理为一个 8 位无符号整数
                    defaultValue = (defaultValue >>> 0).toString(16);
                } else {
                    // dec转16
                    defaultValue = defaultValue.toString(16)
                }
            }
            // 确保去掉 "0x" 并按长度补0
            return defaultValue ? defaultValue.replace(/^0x/, "").padStart(item.bit_length / 4, '0') : "";
        })
        .join(""); // 组合成连续字符串

    // 使用正则匹配每两个字符分割一次
    const formattedString = hexString.match(/.{1,2}/g)?.join(" ") || "";

    return formattedString;
};

export function generateRandomKey(length = 6) {
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
        result += characters[Math.random() * characters.length | 0];
    }
    return result;
}

/**
 * 把uint8数组转成十六进制串
 * @param uint8Array
 * @param separator 分隔符
 */
export function uint8ArrayToHexString(uint8Array, separator = ' ') {
    return Array.from(uint8Array)  // 转换为普通数组
        .map(byte => byte.toString(16).padStart(2, '0'))  // 每个字节转为2位十六进制
        .join(separator);  // 合并成一个连续的十六进制字符串
}

export function hexStringToUint8Array(hexString) {
    hexString = hexString.replace("0x", '').replace(/\s/g, "");
    // 确保十六进制字符串是偶数长度
    if (hexString.length % 2 !== 0) {
        hexString = '0' + hexString;
    }

    // 拆分成两个字符一组
    const byteArray = new Uint8Array(hexString.length / 2);
    for (let i = 0; i < hexString.length; i += 2) {
        byteArray[i / 2] = parseInt(hexString.substring(i, i + 2), 16);
    }

    return byteArray;
}

/**
 * arraybuffer转16进制字符串
 * @param buffer
 * @returns {string}
 */
export function arrayBufferToHex(buffer) {
    return [...new Uint8Array(buffer)]
        .map(x => x.toString(16).padStart(2, '0'))
        .join('');
}
